#![allow(dead_code)]

use chrono::{Datelike, Local, TimeDelta, Timelike, Weekday};
use std::time::Duration;
use tokio::time::{Instant, sleep_until};

async fn sleep_until_next_10min() -> bool {
    let now = Local::now();
    let minutes_to_next = 10 - (now.minute() % 10);
    // 计算到毫秒级精度
    let millis_to_next = minutes_to_next as u64 * 60 * 1_000
        - now.second() as u64 * 1_000
        - now.timestamp_subsec_millis() as u64;

    let deadline = Instant::now() + Duration::from_millis(millis_to_next);

    // 计算deadline对应的日期时间
    let deadline_time = now + chrono::Duration::milliseconds(millis_to_next as i64);

    // 检查是否是周三早上7点整
    let is_wednesday_7am = deadline_time.weekday() == Weekday::Wed
        && deadline_time.hour() == 7
        && deadline_time.minute() == 0;

    sleep_until(deadline).await;

    // 返回检查结果
    is_wednesday_7am
}

pub fn interval_strategy(interval: u64) -> tokio::time::Interval {
    // 定义心跳间隔和超时时间
    let ping_interval = Duration::from_secs(interval);
    tokio::time::interval(ping_interval)
}

pub async fn workday_strategy(hour: u32, minute: u32, second: u32) {
    // 获取当前时间
    let now = Local::now();
    let curr = now.naive_local();
    let curr_date = now.date_naive();

    let mut notify_time = curr_date.and_hms_opt(hour, minute, second).unwrap();

    while notify_time <= curr
        || notify_time.weekday() == Weekday::Sat
        || notify_time.weekday() == Weekday::Sun
    {
        notify_time = notify_time + TimeDelta::days(1);
    }

    tracing::info!("current task will be waked at : {:?}", notify_time);

    let duration = notify_time.signed_duration_since(curr);

    let sleep_duration = duration.to_std().unwrap();
    let wake_time = Instant::now() + sleep_duration;

    sleep_until(wake_time).await;
}

#[macro_export]
macro_rules! spawn_cron_task {
    ($name:expr, $cron_expr:expr, $task:expr) => {{
        use chrono::Datelike;
        use chrono::Local;
        use cron::Schedule;
        use std::str::FromStr;
        let schedule = Schedule::from_str($cron_expr).expect("cron expression invalid !");
        tokio::task::spawn(async move {
            let mut upcoming = schedule.upcoming(Local);

            while let Some(next_time) = upcoming.next() {
                // 执行任务
                let start = std::time::Instant::now();
                match $task.await { 
                    Ok(msgs) => { 
                        tracing::info!(
                            "Task {} completed successfully, cost {} ms",
                            $name,
                            start.elapsed().as_millis()
                        );
                        sq_wecom::notify_all(&msgs, &["ShuiTongYaoNanHai", "DaPengCheng"]).await;
                    },
                    Err(err) => {
                        tracing::error!("Task {} failed: {}", $name, err);
                        sq_wecom::cli()
                            .push_message("DaPengCheng", &err.to_string())
                            .await
                    }
                }
                
                // 计算需要等待的时间
                let now = Local::now();
                if next_time > now {
                    let naive_local = next_time.naive_local();
                    let formatted_time = naive_local.format("%Y-%m-%d %H:%M:%S").to_string();
                    let weekday = naive_local.weekday();
                    tracing::info!("task {} will be waked next time at {formatted_time} {}", $name, weekday);
                    let duration = (next_time - now).to_std().unwrap_or_default();
                    tokio::time::sleep(duration).await;
                }
            }
        });
    }};
}
